package log

import (
	"fmt"
	"io"
	"log"
)

// LoggerLevel 定义日志级别
type LoggerLevel int

// 枚举所有日志级别
const (
	// 以下级别也匹配syslog.Priority值
	LoggerDebug LoggerLevel = iota
	LoggerInfo
	LoggerWarning
	LoggerErr
	LoggerOff
	LoggerUnknown
)

// 默认日志选项
const (
	DefaultLogPrefix = "[orm]"
	DefaultLogFlag   = log.Ldate | log.Lmicroseconds
	DefaultLogLevel  = LoggerDebug
)

// ILogger 是Logger的接口
type ILogger interface {
	Debug(v ...interface{})
	DebugF(format string, v ...interface{})
	Error(v ...interface{})
	ErrorF(format string, v ...interface{})
	Info(v ...interface{})
	InfoF(format string, v ...interface{})
	Warn(v ...interface{})
	WarnF(format string, v ...interface{})
	Level() LoggerLevel
	SetLevel(l LoggerLevel)
	ShowSQL(show ...bool)
	IsShowSQL() bool
}

// DiscardLogger 不要记录 ILogger 的实现
type DiscardLogger struct{}

// Debug empty implementation
func (DiscardLogger) Debug(v ...interface{}) {}

// DebugF empty implementation
func (DiscardLogger) DebugF(format string, v ...interface{}) {}

// Error empty implementation
func (DiscardLogger) Error(v ...interface{}) {}

// ErrorF empty implementation
func (DiscardLogger) ErrorF(format string, v ...interface{}) {}

// Info empty implementation
func (DiscardLogger) Info(v ...interface{}) {}

// InfoF empty implementation
func (DiscardLogger) InfoF(format string, v ...interface{}) {}

// Warn empty implementation
func (DiscardLogger) Warn(v ...interface{}) {}

// WarnF empty implementation
func (DiscardLogger) WarnF(format string, v ...interface{}) {}

// Level empty implementation
func (DiscardLogger) Level() LoggerLevel {
	return LoggerUnknown
}

// SetLevel empty implementation
func (DiscardLogger) SetLevel(l LoggerLevel) {}

// ShowSQL empty implementation
func (DiscardLogger) ShowSQL(show ...bool) {}

// IsShowSQL empty implementation
func (DiscardLogger) IsShowSQL() bool {
	return false
}

// SimpleLogger 是 ILogger 的默认实现
type SimpleLogger struct {
	DEBUG   *log.Logger
	ERR     *log.Logger
	INFO    *log.Logger
	WARN    *log.Logger
	level   LoggerLevel
	showSQL bool
}

// NewSimpleLogger 使用特殊的io.Writer作为记录器输出。
func NewSimpleLogger(out io.Writer) *SimpleLogger {
	return NewSimpleLogger2(out, DefaultLogPrefix, DefaultLogFlag)
}

// NewSimpleLogger2 让您自定义记录器前缀和标志。
func NewSimpleLogger2(out io.Writer, prefix string, flag int) *SimpleLogger {
	return NewSimpleLogger3(out, prefix, flag, DefaultLogLevel)
}

// NewSimpleLogger3 让您自定义记录仪前缀和标志以及logLevel。
func NewSimpleLogger3(out io.Writer, prefix string, flag int, l LoggerLevel) *SimpleLogger {
	return &SimpleLogger{
		DEBUG: log.New(out, fmt.Sprintf("%s [debug] ", prefix), flag),
		ERR:   log.New(out, fmt.Sprintf("%s [error] ", prefix), flag),
		INFO:  log.New(out, fmt.Sprintf("%s [info]  ", prefix), flag),
		WARN:  log.New(out, fmt.Sprintf("%s [warn]  ", prefix), flag),
		level: l,
	}
}

// Error implement ILogger
func (s *SimpleLogger) Error(v ...interface{}) {
	if s.level <= LoggerErr {
		s.ERR.Output(2, fmt.Sprintln(v...))
	}
	return
}

// ErrorF implement ILogger
func (s *SimpleLogger) ErrorF(format string, v ...interface{}) {
	if s.level <= LoggerErr {
		s.ERR.Output(2, fmt.Sprintf(format, v...))
	}
	return
}

// Debug implement ILogger
func (s *SimpleLogger) Debug(v ...interface{}) {
	if s.level <= LoggerDebug {
		s.DEBUG.Output(2, fmt.Sprintln(v...))
	}
	return
}

// DebugF implement ILogger
func (s *SimpleLogger) DebugF(format string, v ...interface{}) {
	if s.level <= LoggerDebug {
		s.DEBUG.Output(2, fmt.Sprintf(format, v...))
	}
	return
}

// Info implement ILogger
func (s *SimpleLogger) Info(v ...interface{}) {
	if s.level <= LoggerInfo {
		s.INFO.Output(2, fmt.Sprintln(v...))
	}
	return
}

// InfoF implement ILogger
func (s *SimpleLogger) InfoF(format string, v ...interface{}) {
	if s.level <= LoggerInfo {
		s.INFO.Output(2, fmt.Sprintf(format, v...))
	}
	return
}

// Warn implement ILogger
func (s *SimpleLogger) Warn(v ...interface{}) {
	if s.level <= LoggerWarning {
		s.WARN.Output(2, fmt.Sprintln(v...))
	}
	return
}

// WarnF implement ILogger
func (s *SimpleLogger) WarnF(format string, v ...interface{}) {
	if s.level <= LoggerWarning {
		s.WARN.Output(2, fmt.Sprintf(format, v...))
	}
	return
}

// Level implement ILogger
func (s *SimpleLogger) Level() LoggerLevel {
	return s.level
}

// SetLevel implement ILogger
func (s *SimpleLogger) SetLevel(l LoggerLevel) {
	s.level = l
	return
}

// ShowSQL implement ILogger
func (s *SimpleLogger) ShowSQL(show ...bool) {
	if len(show) == 0 {
		s.showSQL = true
		return
	}
	s.showSQL = show[0]
}

// IsShowSQL implement ILogger
func (s *SimpleLogger) IsShowSQL() bool {
	return s.showSQL
}
